package com.songyang.mqttandothers.mqttCore;

import lombok.extern.slf4j.Slf4j;
import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
import org.eclipse.paho.client.mqttv3.MqttCallback;
import org.eclipse.paho.client.mqttv3.MqttMessage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;

/**
 * 发布消息的回调类
 * <p>
 * 必须实现MqttCallback的接口并实现对应的相关接口方法CallBack 类将实现 MqttCallBack。
 * 每个客户机标识都需要一个回调实例。在此示例中，构造函数传递客户机标识以另存为实例数据。
 * 在回调中，将它用来标识已经启动了该回调的哪个实例。
 * 必须在回调类中实现三个方法：
 * <p>
 * public void messageArrived(MqttTopic topic, MqttMessage message)接收已经预订的发布。
 * <p>
 * public void connectionLost(Throwable cause)在断开连接时调用。
 * <p>
 * public void deliveryComplete(MqttDeliveryToken token))
 * 接收到已经发布的 QoS 1 或 QoS 2 消息的传递令牌时调用。
 * 由 MqttClient.connect 激活此回调。
 */
@Slf4j
@Component
public class PushCallback implements MqttCallback {
    @Autowired
    private RedisTemplate redisTemplate;
    private String graphKey = "graphMapKey";

    private static PushCallback pushCallback;

    @PostConstruct
    public void init() {
        pushCallback = this;
        pushCallback.redisTemplate = this.redisTemplate;
//        System.out.println(deviceService == null);
    }

    public void connectionLost(Throwable cause) {
        // 连接丢失后，一般在这里面进行重连
//        String message = cause.getMessage();
//        System.out.println("连接断开，可以做重连"+cause.getMessage());
        ClientMQTT.reconnect();
    }

    public void deliveryComplete(IMqttDeliveryToken token) {
        System.out.println("deliveryComplete---------" + token.isComplete());
    }

    public void messageArrived(String topic, MqttMessage message) {
        /**
         * 收到消息以后，向redis的hash和list都放一份
         * 其中hash作为数据的存储，list用来删除之前的数据
         */
        try {
            Double value = null;
            String getMessage = new String(message.getPayload());
            if (!getMessage.equals("close")) {
                if (getMessage != null) {
                    value = Double.valueOf(getMessage);
                    //板子adc转温度
                    value = (value * 3.3 / 4096 - 0.76) / 0.0025 + 25;
//                System.out.println("value = " + value);
                }
                String hashKey = graphKey + ":" + topic;
                String listKey = "list:" + topic;
                String time = getTime().substring(11);
                List range = pushCallback.redisTemplate.opsForList().range(listKey, 0, -1);
                if (range.size() >= 20) {
                    for (int i = 0; i <= range.size() - 20; i++) {
                        String popKey = (String) pushCallback.redisTemplate.opsForList().rightPop(listKey);
                        pushCallback.redisTemplate.opsForHash().delete(hashKey, popKey);
//                log.info("popKey:"+popKey);
                    }
                }
                pushCallback.redisTemplate.opsForList().leftPush(listKey, time);
                pushCallback.redisTemplate.opsForHash().put(hashKey, time, String.valueOf(value));
            }
            log.info("接收消息主题 : " + topic);
            log.info("接收消息Qos : " + message.getQos());
            log.info("接收消息内容 : " + value);
            log.info("----------------------------------");
        } catch (Exception e) {
            log.info("回调函数出现了异常，异常原因:" + e.getMessage());
        }

    }

    public String getTime() {
        Date date = new Date();//创建时间
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss-SSS");
        return format.format(date);
    }
}

